/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.basic.hazard.sds.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.basic.common.constant.enums.ParkBasicModDictEnum;
import com.hopes.bizz.basic.common.constant.enums.ParkBasicSysDictEnum;
import com.hopes.bizz.basic.hazard.sds.dto.HazChemicalSdsExcelDTO;
import com.hopes.bizz.basic.hazard.sds.entity.HazChemicalSdsEntity;
import com.hopes.bizz.basic.hazard.sds.entity.HazChemicalStockEntity;
import com.hopes.bizz.basic.hazard.sds.mapper.HazChemicalSdsMapper;
import com.hopes.bizz.basic.hazard.sds.service.HazChemicalSdsService;
import com.hopes.bizz.basic.hazard.sds.service.HazChemicalStockService;
import com.hopes.bizz.basic.hazard.sds.vo.HazChemicalSdsExcelVO;
import com.hopes.bizz.basic.hazard.sds.vo.HazChemicalStockPageVO;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.SysDictEnum;
import com.hopes.boss.common.core.util.ClassUtils;
import com.hopes.boss.common.entity.ValidateImportBO;
import com.hopes.boss.common.excel.vo.ErrorMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * 企业危险化学品SDS
 *
 * @author daijie
 * @date 2023-11-13 11:10:15
 */
@Service
@Slf4j
public class HazChemicalSdsServiceImpl extends ServiceImpl<HazChemicalSdsMapper, HazChemicalSdsEntity> implements HazChemicalSdsService {

    @Autowired
    private HazChemicalStockService hazChemicalStockService;

    @Override
    public ValidateImportBO<HazChemicalSdsExcelDTO> validateImport(List<HazChemicalSdsExcelDTO> excelDTOList) {
        ValidateImportBO<HazChemicalSdsExcelDTO> bo = new ValidateImportBO<>();
        List<ErrorMessage> errorMessageList = new ArrayList<>();
        List<HazChemicalSdsExcelDTO> saveList = new ArrayList<>();
        int successNum = 0;
        int failedNum = 0;

        for (HazChemicalSdsExcelDTO excelDTO : excelDTOList) {
            final Field[] fields = excelDTO.getClass().getFields();

            // 验证非空字段
            final Set<String> errorMsg = requiredNonNull(excelDTO, fields);

            if (errorMsg.isEmpty()) {
                saveList.add(excelDTO);
                successNum++;
            } else {
                errorMessageList.add(new ErrorMessage(excelDTO.getLineNum(), errorMsg));
                failedNum++;
            }
        }

        bo.setErrorMessages(errorMessageList);
        bo.setSaveList(saveList);
        bo.setSuccessNum(successNum);
        bo.setFailedNum(failedNum);
        return bo;
    }

    /**
     * 验证非空字段
     * @param excelDTO 对象
     * @param fields   所属属性
     * @return         验证结果
     */
    private Set<String> requiredNonNull(HazChemicalSdsExcelDTO excelDTO, Field[] fields) {
        final HashSet<String> result = new HashSet<>();
        for (Field field : fields) {
            final NotNull annotation = field.getAnnotation(NotNull.class);
            if (null == annotation) {
                continue;
            }
            try {
                final Object propertyValue = ClassUtils.getPropertyValue(excelDTO, field.getName());
                if (null == propertyValue || propertyValue.toString().trim().equals("")) {
                    result.add(annotation.message());
                }
            }catch (Exception e) {
                log.error(" class: {}, field:{}, get value error !", excelDTO.getClass(), field.getName());
            }
        }
        return result;
    }

    @Override
    public HazChemicalSdsEntity importDtoToEntity(HazChemicalSdsExcelDTO excelDto) {
        HazChemicalSdsEntity entity= new HazChemicalSdsEntity();
        BeanUtils.copyProperties(excelDto, entity);

        entity.setChemicalType(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.hazard_chemical_type, excelDto.getChemicalType()));
        entity.setStatus(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.hazard_process_status, excelDto.getStatus()));
        entity.setKeyFlag(DictResolver.getItemValueByLabel(SysDictEnum.yes_no_type, excelDto.getKeyFlag(), Boolean::valueOf));
        entity.setSpecialFlag(DictResolver.getItemValueByLabel(SysDictEnum.yes_no_type, excelDto.getSpecialFlag(), Boolean::valueOf));
        entity.setHighlyToxicFlag(DictResolver.getItemValueByLabel(SysDictEnum.yes_no_type, excelDto.getHighlyToxicFlag(), Boolean::valueOf));
        entity.setMiddleStorageFlag(DictResolver.getItemValueByLabel(SysDictEnum.yes_no_type, excelDto.getMiddleStorageFlag(), Boolean::valueOf));
        entity.setExplodeFlag(DictResolver.getItemValueByLabel(SysDictEnum.yes_no_type, excelDto.getExplodeFlag(), Boolean::valueOf));
        entity.setToxicFlag(DictResolver.getItemValueByLabel(SysDictEnum.yes_no_type, excelDto.getToxicFlag(), Boolean::valueOf));
        entity.setPhysicalState(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.hazard_physical_state, excelDto.getPhysicalState()));
        entity.setStability(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.hazard_stability, excelDto.getStability()));
        entity.setPolymerizationHazard(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.haz_polymerization_hazard, excelDto.getPolymerizationHazard()));
        entity.setCombustibility(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.hazard_combustibility, excelDto.getCombustibility()));
        entity.setWarningWord(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.hazard_warning_word, excelDto.getWarningWord()));
        entity.setWarningImgCode(DictResolver.getItemValueByLabel(ParkBasicModDictEnum.pictogram_code, excelDto.getWarningImgCode()));
        return entity;
    }

    @Override
    public HazChemicalSdsExcelVO exportEntityToVo(HazChemicalSdsEntity entity) {
        HazChemicalSdsExcelVO excelVO = new HazChemicalSdsExcelVO();
        BeanUtils.copyProperties(entity, excelVO);

        excelVO.setChemicalType(entity.getChemicalTypeStr());
        excelVO.setStatus(entity.getStatusStr());
        excelVO.setKeyFlag(entity.getKeyFlagStr());
        excelVO.setSpecialFlag(entity.getSpecialFlagStr());
        excelVO.setHighlyToxicFlag(entity.getHighlyToxicFlagStr());
        excelVO.setMiddleStorageFlag(entity.getMiddleStorageFlagStr());
        excelVO.setExplodeFlag(entity.getExplodeFlagStr());
        excelVO.setToxicFlag(entity.getToxicFlagStr());
        excelVO.setPhysicalState(entity.getPhysicalStateStr());
        excelVO.setStability(entity.getStabilityStr());
        excelVO.setPolymerizationHazard(entity.getPolymerizationHazardStr());
        excelVO.setCombustibility(entity.getCombustibilityStr());
        excelVO.setWarningWord(entity.getWarningWordStr());
        excelVO.setWarningImgCode(entity.getWarningImgCodeStr());
        return excelVO;
    }

    @Override
    public Page<HazChemicalStockPageVO> stockPage(Page page, HazChemicalSdsEntity hazChemicalSds) {
        LambdaQueryWrapper<HazChemicalSdsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ObjectUtils.isNotNull(hazChemicalSds.getId()), HazChemicalSdsEntity::getId, hazChemicalSds.getId());
        if (ObjectUtils.isNotNull(hazChemicalSds.getSdsCode())) {
            String sdsCode = hazChemicalSds.getSdsCode();
            wrapper.like(HazChemicalSdsEntity::getName, sdsCode).or()
                    .like(HazChemicalSdsEntity::getSdsCode, sdsCode).or()
                    .like(HazChemicalSdsEntity::getCasNo, sdsCode);
        }
        wrapper.eq(ObjectUtils.isNotNull(hazChemicalSds.getKeyFlag()), HazChemicalSdsEntity::getKeyFlag, hazChemicalSds.getKeyFlag());
        wrapper.eq(ObjectUtils.isNotNull(hazChemicalSds.getSpecialFlag()), HazChemicalSdsEntity::getSpecialFlag, hazChemicalSds.getSpecialFlag());
        wrapper.eq(ObjectUtils.isNotNull(hazChemicalSds.getChemicalType()), HazChemicalSdsEntity::getChemicalType, hazChemicalSds.getChemicalType());

        Page<HazChemicalSdsEntity> sdsEntityPage = this.page(page, wrapper);
        List<HazChemicalStockPageVO> voList = new ArrayList<>();
        Page<HazChemicalStockPageVO> stockPageVOPage = new Page<>(sdsEntityPage.getCurrent(), sdsEntityPage.getSize(), sdsEntityPage.getTotal(), sdsEntityPage.searchCount());
        stockPageVOPage.setRecords(voList);

        for (HazChemicalSdsEntity record : sdsEntityPage.getRecords()) {
            HazChemicalStockPageVO vo = new HazChemicalStockPageVO();
            BeanUtils.copyProperties(record, vo);

            HazChemicalStockEntity stockEntity = hazChemicalStockService.getOne(Wrappers.lambdaQuery(HazChemicalStockEntity.class)
                    .eq(HazChemicalStockEntity::getSdsId, record.getId()));
            if (stockEntity != null) {
                BeanUtils.copyProperties(stockEntity, vo);
                voList.add(vo);
            }
        }

        return stockPageVOPage;
    }

    @Override
    public boolean save(HazChemicalSdsEntity entity) {
        super.save(entity);

        HazChemicalStockEntity stockEntity = new HazChemicalStockEntity();
        stockEntity.setSdsId(entity.getId());
        stockEntity.setCasNo(entity.getCasNo());
        stockEntity.setKeyFlag(entity.getKeyFlag());
        stockEntity.setDataTime(new Date());
        stockEntity.setStockNum(BigDecimal.ZERO);
        stockEntity.setInNum(BigDecimal.ZERO);
        stockEntity.setOutNum(BigDecimal.ZERO);

        return hazChemicalStockService.save(stockEntity);
    }
}
